package com.central.apps.controller;

import com.central.app.common.util.DateUtils;
import com.central.app.service.HandlerService;
import com.central.apps.common.feign.AuthClient;
import com.central.common.exception.service.ServiceException;
import com.central.common.model.SysUser;
import com.central.common.util.MD5Util;
import com.central.common.web.Result;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.MimeHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;

/**
 * 单点登录
 *
 * @author JHY
 */
@Slf4j
@Api(tags = "单点登录")
@CrossOrigin
@RestController
@RequestMapping("/ssoLogin")
public class SSOLoginController {
    @Autowired
    private HandlerService handlerService;
    @Autowired
    private AuthClient authClient;

    @RequestMapping("/login")
    public Map<String, Object> login(String loginName, String sign, HttpServletRequest request, HttpServletResponse response) throws Exception {
        Map<String, Object> result = new HashMap<>(1);

        // 1.查询是否存在登录用户
        Map<String, Object> userMap = handlerService.findOneBySql("select id from sys_user where username = '" + loginName + "'");
        if (ObjectUtils.isEmpty(userMap)) {
            result.put("resp_code", HttpStatus.UNAUTHORIZED.value());
            result.put("rsp_msg", "登录用户名不存在!");
            return result;
        }

        // 2.组织MD5签名信息
        String encryptSign = "";
        try {
            encryptSign = combineSign(loginName);
        } catch (Exception e) {
            result.put("resp_code", HttpStatus.UNAUTHORIZED.value());
            result.put("rsp_msg", e.getMessage());
            return result;
        }

        if (StringUtils.isNotEmpty(encryptSign) && sign.trim().equalsIgnoreCase(encryptSign)) {
            /**
             * 返回数据格式
             * access_token: "7899ce4c-2dbd-473f-9608-f62290da6981"
             * expires_in: 942
             * refresh_token: "a93f48d6-3d61-4cb6-b022-28e4c3186956"
             * scope: "app"
             * token_type: "bearer"
             */
            Map<String, Object> tokenMap = authClient.getUserTokenInfoByName(loginName, request, response);
            String token = MapUtils.getString(tokenMap,"token_type") + " " + MapUtils.getString(tokenMap,"access_token");

            // 系统访问地址
            Map<String, Object> map = handlerService.findOneBySql("select paramvalue from gq_pcline where paramcode = 'url' and pcid in (select id from gq_paramconfig where pcnum = 'SYS_URL' and status = '可用')");

            if (ObjectUtils.isEmpty(map)) {
                throw new ServiceException("未配置当前系统访问地址!");
            }

            String url = MapUtils.getString(map, "paramvalue") + "?token=" + token;

            request.setCharacterEncoding("utf-8");
            // 设置header Authorization信息
//            setHeaderAuthorization(request, token);

            response.sendRedirect(url);

            result.put("resp_code", HttpStatus.OK.value());
            result.put("rsp_msg", "登录成功!");
            return result;
        }

        result.put("resp_code", HttpStatus.UNAUTHORIZED.value());
        result.put("rsp_msg", "登录失败!");
        return result;
    }

    // http://192.168.80.168:8866/api-apps/ssoLogin/sendRedirect
    // http://127.0.0.1:30407/ssoLogin/sendRedirect
    @RequestMapping("/sendRedirect")
    public void sendRedirect(String token, String app, String appDesc,
                             String appid, String bizId, String menucode,
                             HttpServletRequest request, HttpServletResponse response) throws IOException {
        String url = String.format("http://192.168.80.168:8866/#/index?token=%s&app=%s&appDesc=%s&appid=%s&bizId=%s&menucode=%s",
                token, app, appDesc, appid, bizId, menucode);
        System.out.println("o URL:" + url);
        request.setCharacterEncoding("utf-8");
        System.out.println("URL:" + url);
        response.sendRedirect(url);
    }

    /**
     * 全量同步
     *
     * @return
     */
    @RequestMapping("/fullSync")
    public Result fullSync() throws Exception {
        // 调用 OA系统 获取用户列表
        List<SysUser> sysUsers = new ArrayList<>();
        SysUser s1 = new SysUser();
        s1.setId(1100L);
        s1.setUsername("fanwei1");
        s1.setPassword("$2a$10$nMqj7mDgyV6QfgXSI60AWepOPyPD57fhW6n9tZzZKwmyqVAhatLd.");
//        s1.setWeiinfo("");
        s1.setNickname("fanwei1");
        s1.setHeadimgurl("http://payo7kq4i.bkt.clouddn.com/耳机.jpg");
        s1.setPhone("15298789762");
        s1.setSex(1);
        s1.setEnabled(true);
        s1.setType("backend");
        s1.setDelFlag("0");
        s1.setCreateuser("100001");
        s1.setUpdateuser("100001");
        s1.setCreatetime(new Date());
        s1.setUpdatetime(new Date());
        sysUsers.add(s1);

        // 批量插入 sys_user
        List<Map<String, Object>> datas = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        for (SysUser sysUser : sysUsers) {
            Long id = sysUser.getId();
            if (id != null) {
                map.put("id", id);
            }
            String username = sysUser.getUsername();
            if (StringUtils.isNotBlank(username)){
                map.put("username", username);
            }
            String password = sysUser.getPassword();
            if (StringUtils.isNotBlank(password)){
                map.put("password", password);
            }
            String nickname = sysUser.getNickname();
            if (StringUtils.isNotBlank(nickname)){
                map.put("nickname", nickname);
            }
            String headimgurl = sysUser.getHeadimgurl();
            if (StringUtils.isNotBlank(headimgurl)){
                map.put("headimgurl", headimgurl);
            }
        }
        datas.add(map);

        handlerService.batchInsert("assetcolldetailApp", "sys_user", datas);
        return Result.succeed("成功");
    }

    /**
     * 设置header Authorization信息
     *
     * @param request
     * @param token
     */
    private void setHeaderAuthorization(HttpServletRequest request, String token) {
        Class<? extends HttpServletRequest> requestClass = request.getClass();

        try {
            Field request1 = requestClass.getDeclaredField("request");
            request1.setAccessible(true);
            Object o = request1.get(request);
            Field cpyoteRequest = o.getClass().getDeclaredField("coyoteRequest");
            cpyoteRequest.setAccessible(true);
            Object o1 = cpyoteRequest.get(o);
            Field headers = o.getClass().getDeclaredField("headers");
            headers.setAccessible(true);
            MimeHeaders o2 = (MimeHeaders) headers.get(o1);
            o2.addValue("Authorization").setString(token);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 验证token
     *
     * @param token 令牌
     * @return boolean
     */
    public boolean isTokenExpired(String token) {
        OAuth2AccessToken accessToken = authClient.getTokenInfo(token);
        if (accessToken == null || accessToken.isExpired()) {
            return true;
        }
        return false;
    }

    /**
     * 组织签名
     *
     * @param loginName 登录用户名
     * @return 签名
     */
    private String combineSign(String loginName) throws Exception {
        // 获取当前日期yyyy-MM-dd字符串
        String nowDate = DateUtils.getCurrentString();

        // OA惟一key
        Map<String, Object> map = handlerService.findOneBySql("select paramvalue from gq_pcline where paramcode = 'key' and pcid in (select id from gq_paramconfig where pcnum = 'OA_KEY' and status = '可用')");

        if (ObjectUtils.isEmpty(map)) {
            throw new ServiceException("未配置约定key!");
        }

        String key = MapUtils.getString(map, "paramvalue");

        // 拼接签名字符串
        String signStr = key + loginName + nowDate;

        // MD5加密后返回
        return MD5Util.md5Hex(signStr);
    }
}
